/*-------------------------------------------------------------------------
 *
 * gtm_utils.c
 *  Utililies of GTM
 *
 * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
 * Portions Copyright (c) 1994, Regents of the University of California
 * Portions Copyright (c) 2010-2012 Postgres-XC Development Group
 *
 *
 * IDENTIFICATION
 *		src/gtm/common/gtm_utils.c
 *
 *-------------------------------------------------------------------------
 */
#include "gtm/gtm_utils.h"
#include "gtm/elog.h"
#include "gtm/gtm.h"
#include "gtm/gtm_msg.h"
#include "gtm/memutils.h"

struct enum_name
{
	int type;
	char *name;
};

/*
 * Advise:
 * Following table can be formatted using gtm_msg.h definitions.
 */
static struct enum_name message_name_tab[] =
{
	{MSG_TYPE_INVALID, "MSG_TYPE_INVALID"},
	{MSG_SYNC_STANDBY, "MSG_SYNC_STANDBY"},
	{MSG_NODE_REGISTER, "MSG_NODE_REGISTER"},
	{MSG_BKUP_NODE_REGISTER, "MSG_BKUP_NODE_REGISTER"},
	{MSG_NODE_UNREGISTER, "MSG_NODE_UNREGISTER"},
	{MSG_BKUP_NODE_UNREGISTER, "MSG_BKUP_NODE_UNREGISTER"},
	{MSG_REGISTER_SESSION, "MSG_REGISTER_SESSION"},
	{MSG_REPORT_XMIN, "MSG_REPORT_XMIN"},
	{MSG_NODE_LIST, "MSG_NODE_LIST"},
	{MSG_NODE_BEGIN_REPLICATION_INIT, "MSG_NODE_BEGIN_REPLICATION_INIT"},
	{MSG_NODE_END_REPLICATION_INIT, "MSG_NODE_END_REPLICATION_INIT"},
	{MSG_BEGIN_BACKUP, "MSG_BEGIN_BACKUP"},
	{MSG_END_BACKUP, "MSG_END_BACKUP"},
	{MSG_TXN_BEGIN, "MSG_TXN_BEGIN"},
	{MSG_BKUP_TXN_BEGIN, "MSG_BKUP_TXN_BEGIN"},
	{MSG_BKUP_GLOBAL_TIMESTAMP, "MSG_BKUP_GLOBAL_TIMESTAMP"},
	{MSG_TXN_BEGIN_GETGXID, "MSG_TXN_BEGIN_GETGXID"},	
	{MSG_BKUP_TXN_BEGIN_GETGXID, "MSG_BKUP_TXN_BEGIN_GETGXID"},
	{MSG_TXN_BEGIN_GETGXID_MULTI, "MSG_TXN_BEGIN_GETGXID_MULTI"},
	{MSG_BKUP_TXN_BEGIN_GETGXID_MULTI, "MSG_BKUP_TXN_BEGIN_GETGXID_MULTI"},
	{MSG_TXN_START_PREPARED, "MSG_TXN_START_PREPARED"},
	{MSG_BKUP_TXN_START_PREPARED, "MSG_BKUP_TXN_START_PREPARED"},
	{MSG_TXN_COMMIT, "MSG_TXN_COMMIT"},
	{MSG_BKUP_TXN_COMMIT, "MSG_BKUP_TXN_COMMIT"},
	{MSG_TXN_LOG_GLOBAL_COMMIT, "MSG_TXN_LOG_GLOBAL_COMMIT"},
	{MSG_TXN_LOG_COMMIT, "MSG_TXN_LOG_COMMIT"},
	{MSG_TXN_LOG_GLOBAL_SCAN, "MSG_TXN_LOG_GLOBAL_SCAN"},
	{MSG_TXN_LOG_SCAN, "MSG_TXN_LOG_SCAN"},
	{MSG_TXN_COMMIT_MULTI, "MSG_TXN_COMMIT_MULTI"},
	{MSG_BKUP_TXN_COMMIT_MULTI, "MSG_BKUP_TXN_COMMIT_MULTI"},
	{MSG_TXN_COMMIT_PREPARED, "MSG_TXN_COMMIT_PREPARED"},
	{MSG_BKUP_TXN_COMMIT_PREPARED, "MSG_BKUP_TXN_COMMIT_PREPARED"},
	{MSG_TXN_PREPARE, "MSG_TXN_PREPARE"},
	{MSG_BKUP_TXN_PREPARE, "MSG_BKUP_TXN_PREPARE"},
	{MSG_TXN_ROLLBACK, "MSG_TXN_ROLLBACK"},
	{MSG_BKUP_TXN_ROLLBACK, "MSG_BKUP_TXN_ROLLBACK"},
	{MSG_TXN_ROLLBACK_MULTI, "MSG_TXN_ROLLBACK_MULTI"},
	{MSG_BKUP_TXN_ROLLBACK_MULTI, "MSG_BKUP_TXN_ROLLBACK_MULTI"},
	{MSG_TXN_GET_GID_DATA, "MSG_TXN_GET_GID_DATA"},
	{MSG_TXN_GET_GXID, "MSG_TXN_GET_GXID"},
	{MSG_BKUP_TXN_GET_GXID, "MSG_BKUP_TXN_GET_GXID"},
	{MSG_TXN_GET_NEXT_GXID, "MSG_TXN_GET_NEXT_GXID"},
	{MSG_TXN_GXID_LIST, "MSG_TXN_GXID_LIST"},
	{MSG_SNAPSHOT_GET, "MSG_SNAPSHOT_GET"},
	{MSG_SNAPSHOT_GET_MULTI, "MSG_SNAPSHOT_GET_MULTI"},
	{MSG_SNAPSHOT_GXID_GET, "MSG_SNAPSHOT_GXID_GET"},
	{MSG_SEQUENCE_INIT, "MSG_SEQUENCE_INIT"},
	{MSG_BKUP_SEQUENCE_INIT, "MSG_BKUP_SEQUENCE_INIT"},
	{MSG_SEQUENCE_GET_CURRENT, "MSG_SEQUENCE_GET_CURRENT"},
	{MSG_SEQUENCE_GET_NEXT, "MSG_SEQUENCE_GET_NEXT"},
	{MSG_BKUP_SEQUENCE_GET_NEXT, "MSG_BKUP_SEQUENCE_GET_NEXT"},
	{MSG_SEQUENCE_GET_LAST, "MSG_SEQUENCE_GET_LAST"},
	{MSG_SEQUENCE_SET_VAL, "MSG_SEQUENCE_SET_VAL"},
	{MSG_BKUP_SEQUENCE_SET_VAL, "MSG_BKUP_SEQUENCE_SET_VAL"},
	{MSG_SEQUENCE_RESET, "MSG_SEQUENCE_RESET"},
	{MSG_BKUP_SEQUENCE_RESET, "MSG_BKUP_SEQUENCE_RESET"},
	{MSG_SEQUENCE_CLOSE, "MSG_SEQUENCE_CLOSE"},
	{MSG_BKUP_SEQUENCE_CLOSE, "MSG_BKUP_SEQUENCE_CLOSE"},
	{MSG_SEQUENCE_RENAME, "MSG_SEQUENCE_RENAME"},
	{MSG_BKUP_SEQUENCE_RENAME, "MSG_BKUP_SEQUENCE_RENAME"},
	{MSG_BKUP_SEQUENCE_RENAME, "MSG_BKUP_SEQUENCE_RENAME"},
	{MSG_SEQUENCE_ALTER, "MSG_SEQUENCE_ALTER"},
	{MSG_BKUP_SEQUENCE_ALTER, "MSG_BKUP_SEQUENCE_ALTER"},
	{MSG_SEQUENCE_LIST, "MSG_SEQUENCE_LIST"},
	{MSG_TXN_GET_STATUS, "MSG_TXN_GET_STATUS"},
	{MSG_TXN_GET_ALL_PREPARED, "MSG_TXN_GET_ALL_PREPARED"},
	{MSG_TXN_BEGIN_GETGXID_AUTOVACUUM, "MSG_TXN_BEGIN_GETGXID_AUTOVACUUM"},
	{MSG_BKUP_TXN_BEGIN_GETGXID_AUTOVACUUM, "MSG_BKUP_TXN_BEGIN_GETGXID_AUTOVACUUM"},
	{MSG_DATA_FLUSH, "MSG_DATA_FLUSH"},
	{MSG_BACKEND_DISCONNECT, "MSG_BACKEND_DISCONNECT"},
	{MSG_BARRIER,	"MSG_BARRIER"},
	{MSG_BKUP_BARRIER,	"MSG_BKUP_BARRIER"},

#ifdef __OPENTENBASE__
	{MSG_GET_STORAGE, "MSG_GET_STORAGE"},	
	{MSG_TXN_FINISH_GID, "MSG_TXN_FINISH_GID"},
	{MSG_LIST_GTM_STORE, "MSG_LIST_GTM_STORE"},
	{MSG_LIST_GTM_STORE_SEQ, "MSG_LIST_GTM_STORE_SEQ"},
	{MSG_LIST_GTM_STORE_TXN, "MSG_LIST_GTM_STORE_TXN"},
	{MSG_CHECK_GTM_STORE_SEQ, "MSG_CHECK_GTM_STORE_SEQ"},
	{MSG_CHECK_GTM_STORE_TXN, "MSG_CHECK_GTM_STORE_TXN"},
	{MSG_CLEAN_SESSION_SEQ, "MSG_CLEAN_SESSION_SEQ"},

	{MSG_GETGTS,	"MSG_GETGTS"},				
	{MSG_GETGTS_MULTI, "MSG_GETGTS_MULTI"},

	{MSG_CHECK_GTM_STATUS, "MSG_CHECK_GTM_STATUS"},
	
	{MSG_DB_SEQUENCE_RENAME,	"MSG_DB_SEQUENCE_RENAME"},
	{MSG_BKUP_DB_SEQUENCE_RENAME,	"MSG_BKUP_DB_SEQUENCE_RENAME"},
#endif

#ifdef __XLOG__
	{MSG_START_REPLICATION,"MSG_START_REPLICATION"},
	{MSG_GET_REPLICATION_STATUS,"MSG_GET_REPLICATION_STATUS"},
	{MSG_GET_REPLICATION_TRANSFER,"MSG_GET_REPLICATION_TRANSFER"},
#endif
    {MSG_GET_STATISTICS, "MSG_GET_STATISTICS"},
    {MSG_GET_ERRORLOG, "MSG_GET_ERRORLOG"},
    {MSG_SEQUENCE_COPY, "MSG_SEQUENCE_COPY"},

#ifdef __OPENTENBASE_C__
	{MSG_ACQUIRE_FID,	"MSG_ACQUIRE_FID"},
	{MSG_RELEASE_FID,	"MSG_RELEASE_FID"},
	{MSG_RELEASE_NODE_FID,	"MSG_RELEASE_NODE_FID"},
	{MSG_KEEPALIVE_FID,	"MSG_KEEPALIVE_FID"},
	{MSG_LIST_FID,	"MSG_LIST_FID"},
	{MSG_LIST_ALIVE_FID,	"MSG_LIST_ALIVE_FID"},
	{MSG_LIST_ALL_FID,	"MSG_LIST_ALL_FID"},
#endif

#ifdef __RESOURCE_QUEUE__
	{MSG_RESQUEUE_INIT,	"MSG_RESQUEUE_INIT"},			/* Initialize a new global resqueue */
	{MSG_RESQUEUE_CLOSE,	"MSG_RESQUEUE_CLOSE"},			/* Close a previously inited resqueue */
	{MSG_RESQUEUE_ALTER,	"MSG_RESQUEUE_ALTER"},			/* Alter a resqueue */
	{MSG_RESQUEUE_LIST,	"MSG_RESQUEUE_LIST"},			/* Get a list of resqueues */
	{MSG_RESQUEUE_MOVE_CONN,	"MSG_RESQUEUE_MOVE_CONN"},	/* Just dispatch connect to ResourceQueueManager  */
	{MSG_RESQUEUE_ACQUIRE,	"MSG_RESQUEUE_ACQUIRE"},	/* Acqurie resource from resqueue, Do real acquire resource from ResourceQueueManager */
	{MSG_RESQUEUE_RELEASE,	"MSG_RESQUEUE_RELEASE"},		/* Release resource back to resqueue */
	{MSG_RESQUEUE_IF_EXISTS,	"MSG_RESQUEUE_IF_EXISTS"},		/* Check whether the resource queue exists */

	{MSG_LIST_GTM_STORE_RESQUEUE,	"MSG_LIST_GTM_STORE_RESQUEUE"},			/* List  gtm running resqueue info */
	{MSG_CHECK_GTM_STORE_RESQUEUE,	"MSG_CHECK_GTM_STORE_RESQUEUE"},			/* Check gtm resqueue usage info */
	{MSG_LIST_RESQUEUE_USAGE,	"MSG_LIST_RESQUEUE_USAGE"},			/* list usage info of resource queue */
#endif
	{MSG_TYPE_COUNT, "MSG_TYPE_COUNT"},

	{-1, NULL}
};

static struct enum_name result_name_tab[] =
{
	{SYNC_STANDBY_RESULT, "SYNC_STANDBY_RESULT"},
	{NODE_REGISTER_RESULT, "NODE_REGISTER_RESULT"},
	{NODE_UNREGISTER_RESULT, "NODE_UNREGISTER_RESULT"},
	{REGISTER_SESSION_RESULT, "REGISTER_SESSION_RESULT"},
	{REPORT_XMIN_RESULT, "REPORT_XMIN_RESULT"},
	{NODE_LIST_RESULT, "NODE_LIST_RESULT"},
	{NODE_BEGIN_REPLICATION_INIT_RESULT, "NODE_BEGIN_REPLICATION_INIT_RESULT"},
	{NODE_END_REPLICATION_INIT_RESULT, "NODE_END_REPLICATION_INIT_RESULT"},
	{BEGIN_BACKUP_SUCCEED_RESULT, "BEGIN_BACKUP_SUCCEED_RESULT"},
	{BEGIN_BACKUP_FAIL_RESULT, "BEGIN_BACKUP_FAIL_RESULT"},	
	{END_BACKUP_RESULT, "END_BACKUP_RESULT"},
	{TXN_BEGIN_RESULT, "TXN_BEGIN_RESULT"},
	{TXN_BEGIN_GETGXID_RESULT, "TXN_BEGIN_GETGXID_RESULT"},
	{TXN_BEGIN_GETGTS_RESULT, "TXN_BEGIN_GETGTS_RESULT"},
	{TXN_BEGIN_GETGXID_MULTI_RESULT, "TXN_BEGIN_GETGXID_MULTI_RESULT"},
	{TXN_BEGIN_GETGTS_MULTI_RESULT, "TXN_BEGIN_GETGTS_MULTI_RESULT"},
	{TXN_CHECK_GTM_STATUS_RESULT,	"TXN_CHECK_GTM_STATUS_RESULT"},
	{TXN_PREPARE_RESULT, "TXN_PREPARE_RESULT"},
	{TXN_START_PREPARED_RESULT, "TXN_START_PREPARED_RESULT"},
	{TXN_LOG_TRANSACTION_RESULT, "TXN_LOG_TRANSACTION_RESULT"},
	{TXN_LOG_SCAN_RESULT, "TXN_LOG_SCAN_RESULT"},
	{TXN_COMMIT_PREPARED_RESULT, "TXN_COMMIT_PREPARED_RESULT"},
	{TXN_COMMIT_RESULT, "TXN_COMMIT_RESULT"},
	{TXN_COMMIT_MULTI_RESULT, "TXN_COMMIT_MULTI_RESULT"},
	{TXN_ROLLBACK_RESULT, "TXN_ROLLBACK_RESULT"},
	{TXN_ROLLBACK_MULTI_RESULT, "TXN_ROLLBACK_MULTI_RESULT"},
	{TXN_GET_GID_DATA_RESULT, "TXN_GET_GID_DATA_RESULT"},
	{TXN_GET_GXID_RESULT, "TXN_GET_GXID_RESULT"},
	{TXN_GET_NEXT_GXID_RESULT, "TXN_GET_NEXT_GXID_RESULT"},
	{TXN_GXID_LIST_RESULT, "TXN_GXID_LIST_RESULT"},
	{SNAPSHOT_GET_RESULT, "SNAPSHOT_GET_RESULT"},
	{SNAPSHOT_GET_MULTI_RESULT, "SNAPSHOT_GET_MULTI_RESULT"},
	{SNAPSHOT_GXID_GET_RESULT, "SNAPSHOT_GXID_GET_RESULT"},
	{SEQUENCE_INIT_RESULT, "SEQUENCE_INIT_RESULT"},
	{SEQUENCE_GET_CURRENT_RESULT, "SEQUENCE_GET_CURRENT_RESULT"},
	{SEQUENCE_GET_NEXT_RESULT, "SEQUENCE_GET_NEXT_RESULT"},
	{SEQUENCE_GET_LAST_RESULT, "SEQUENCE_GET_LAST_RESULT"},
	{SEQUENCE_SET_VAL_RESULT, "SEQUENCE_SET_VAL_RESULT"},
	{SEQUENCE_RESET_RESULT, "SEQUENCE_RESET_RESULT"},
	{SEQUENCE_CLOSE_RESULT, "SEQUENCE_CLOSE_RESULT"},
	{SEQUENCE_RENAME_RESULT, "SEQUENCE_RENAME_RESULT"},
	{SEQUENCE_ALTER_RESULT, "SEQUENCE_ALTER_RESULT"},
	{SEQUENCE_LIST_RESULT, "SEQUENCE_LIST_RESULT"},
	{TXN_GET_STATUS_RESULT, "TXN_GET_STATUS_RESULT"},
	{TXN_GET_ALL_PREPARED_RESULT, "TXN_GET_ALL_PREPARED_RESULT"},
	{TXN_BEGIN_GETGXID_AUTOVACUUM_RESULT, "TXN_BEGIN_GETGXID_AUTOVACUUM_RESULT"},
	{BARRIER_RESULT,	"BARRIER_RESULT"},

#ifdef __OPENTENBASE__	
	{STORAGE_TRANSFER_RESULT, "STORAGE_TRANSFER_RESULT"},	
	{TXN_FINISH_GID_RESULT, "TXN_FINISH_GID_RESULT"},
	{MSG_LIST_GTM_STORE_RESULT,	"MSG_LIST_GTM_STORE_RESULT"},
	{MSG_LIST_GTM_STORE_SEQ_RESULT,	"MSG_LIST_GTM_STORE_SEQ_RESULT"},	/* List  gtm running sequence info */
	{MSG_LIST_GTM_TXN_STORE_RESULT,	"MSG_LIST_GTM_TXN_STORE_RESULT"},	/* List  gtm running transaction info */
	{MSG_CHECK_GTM_SEQ_STORE_RESULT,	"MSG_CHECK_GTM_SEQ_STORE_RESULT"},	/* Check gtm sequence usage info */
	{MSG_CHECK_GTM_TXN_STORE_RESULT,	"MSG_CHECK_GTM_TXN_STORE_RESULT"},	/* Check gtm transaction usage info */
	{MSG_CLEAN_SESSION_SEQ_RESULT,	"MSG_CLEAN_SESSION_SEQ_RESULT"}, 
	{MSG_DB_SEQUENCE_RENAME_RESULT, "DB_SEQUENCE_RENAME_RESULT"},
#endif
    {MSG_GET_GTM_STATISTICS_RESULT, "MSG_GET_GTM_STATISTICS_RESULT"},
    {MSG_GET_GTM_ERRORLOG_RESULT, "MSG_GET_GTM_ERRORLOG_RESULT"},
    {SEQUENCE_COPY_RESULT, "SEQUENCE_COPY_RESULT"},

#ifdef __XLOG__
    {MSG_REPLICATION_START_RESULT_SUCCESS,	"MSG_REPLICATION_START_RESULT_SUCCESS"},
    {MSG_REPLICATION_START_RESULT_FAIL,	"MSG_REPLICATION_START_RESULT_FAIL"},
    {MSG_REPLICATION_STATUS,	"MSG_REPLICATION_STATUS"},
    {MSG_REPLICATION_CONTENT,	"MSG_REPLICATION_CONTENT"},
#endif

#ifdef __OPENTENBASE_C__
	{MSG_ACQUIRE_FID_RESULT,	"MSG_ACQUIRE_FID_RESULT"},
	{MSG_RELEASE_FID_RESULT,	"MSG_RELEASE_FID_RESULT"},
	{MSG_KEEPALIVE_FID_RESULT,	"MSG_KEEPALIVE_FID_RESULT"},
	{MSG_LIST_FID_RESULT,	"MSG_LIST_FID_RESULT"},
	{MSG_LIST_ALIVE_FID_RESULT,	"MSG_LIST_ALIVE_FID_RESULT"},
	{MSG_LIST_ALL_FID_RESULT,	"MSG_LIST_ALL_FID_RESULT"},
#endif

#ifdef __RESOURCE_QUEUE__
	{RESQUEUE_INIT_RESULT,	"RESQUEUE_INIT_RESULT"},
	{RESQUEUE_CLOSE_RESULT,	"RESQUEUE_CLOSE_RESULT"},
	{RESQUEUE_ALTER_RESULT,	"RESQUEUE_ALTER_RESULT"},
	{RESQUEUE_LIST_RESULT,	"RESQUEUE_LIST_RESULT"},
	{RESQUEUE_MOVE_CONN_RESULT, "RESQUEUE_MOVE_CONN_RESULT"},
	{RESQUEUE_ACQUIRE_RESULT,	"RESQUEUE_ACQUIRE_RESULT"},
	{RESQUEUE_RELEASE_RESULT, "RESQUEUE_RELEASE_RESULT"},
	{RESQUEUE_IF_EXISTS_RESULT, "RESQUEUE_IF_EXISTS_RESULT"},

	{MSG_LIST_GTM_STORE_RESQUEUE_RESULT,	"MSG_LIST_GTM_STORE_RESQUEUE_RESULT"},		/* List  gtm running resqueue info */
	{MSG_CHECK_GTM_RESQUEUE_STORE_RESULT,	"MSG_CHECK_GTM_RESQUEUE_STORE_RESULT"},	/* Check gtm resqueue usage info */
	{MSG_LIST_RESQUEUE_USAGE_RESULT,	"MSG_LIST_RESQUEUE_USAGE_RESULT"},		/* list usage info of resource queue */
#endif

	{RESULT_TYPE_COUNT, "RESULT_TYPE_COUNT"},

	{-1, NULL}
};

static char **message_name = NULL;
static int message_max;
static char **result_name = NULL;
static int result_max;

void gtm_util_init_nametabs(void)
{
	int ii;

	if (message_name)
		pfree(message_name);
	if (result_name)
		pfree(result_name);
	for (ii = 0, message_max = 0; message_name_tab[ii].type >= 0; ii++)
	{
		if (message_max < message_name_tab[ii].type)
			message_max = message_name_tab[ii].type;
	}
	message_name = (char **)MemoryContextAllocZero(TopMemoryContext, sizeof(char *) * (message_max + 1));
	for (ii = 0; message_name_tab[ii].type >= 0; ii++)
	{
		message_name[message_name_tab[ii].type] = message_name_tab[ii].name;
	}

	for (ii = 0, result_max = 0; result_name_tab[ii].type >= 0; ii++)
	{
		if (result_max < result_name_tab[ii].type)
			result_max = result_name_tab[ii].type;
	}
	result_name = (char **)MemoryContextAllocZero(TopMemoryContext, sizeof(char *) * (result_max + 1));
	for (ii = 0; result_name_tab[ii].type >= 0; ii++)
	{
		result_name[result_name_tab[ii].type] = result_name_tab[ii].name;
	}
}

char *gtm_util_message_name(GTM_MessageType type)
{
	if (message_name == NULL)
		gtm_util_init_nametabs();
	if (type > message_max)
		return "UNKNOWN_MESSAGE";
	return message_name[type];
}

char *gtm_util_result_name(GTM_ResultType type)
{
	if (result_name == NULL)
		gtm_util_init_nametabs();
	if (type > result_max)
		return "UNKNOWN_RESULT";
	return result_name[type];
}
